#pragma once

#include <vex/functional/contract/event.h>
#include <vex/functional/result.h>
#include <vex/functional/replace_result.h>

namespace vex { namespace functional { namespace contract {
    /// <summary>
    /// Invokable event. Used mainly in service contract implementations which
    /// expose an <c>event</c> as an endpoint of a multicast service. The semantics
    /// is equivalent to a mutable <c>multicast_delegate</c>.
    /// </summary>
    template<class TSignature, class TRet = typename result<TSignature>::type>
    struct VEX_ABSTRACT invokable_event
        : public event<TSignature>
        , public delegate<typename replace_result<TSignature, TRet>::type>
    {
        typedef TSignature signature_type;
        typedef TRet result_type;

        /// <summary>
        /// Accepted delegate type
        /// </summary>
        typedef delegate<TSignature> delegate_type;

        /// <summary>
        /// Type of the invocation list
        /// </summary>
        typedef iterable::contract::range<
            iterable::one_pass, 
            delegate_type*
        > invocation_list_type;

        /// <summary>
        /// Implementations shall return the copy of the current snapshot of the invocation list.
        /// </summary>
        virtual invocation_list_type* get_invocation_list() const = 0;

        VEX_PROTECT_CONTRACT(invokable_event);
    };

}}}